<?php
/*
 * dbmaster.php
 *
 * Copyright (C) 2006 - OS3 srl - http://www.os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

// DBMaster
//
// This is the one and only interface for all Database operations
class dbmaster
{
	var $prefix;	// Tables prefix (default: "wb")
	var $dbh;  	// Database Handler
	var $debug = 0;

	function dbmaster ()
	{
		$this->prefix = DB_PREFIX;

		$this->_open ();
		$this->rows = 0;
		$this->cols = 0;

		$this->reduce = true;
	}

	// Check whether a particular table exists
	// NOTE: table name MUST be without prefix
	//
	// If do_prefix is FALSE, we do not add prefix in query
	function exists ( $table_name, $do_prefix = true )
	{
		$tabs = & $this->get_table_list ();

		foreach ( $tabs as $t ) if ( strcasecmp ( $t, $table_name ) == 0 ) return ( true );

		return ( false );			
	}

	function drop_table ( $table_name, $do_prefix = true )
	{
		if ( $do_prefix )
			$sql = "DROP TABLE " . $this->prefix . "_$table_name";
		else
			$sql = "DROP TABLE $table_name";

		$this->_do_query ( $sql, false, false );

		return ( true );
	}

	function & query ( $sql, $show_query = false )
	{
		$f = false;

		if ( $show_query ) print ( "<h1>SQL: $sql</h1>" );

		$res = & $this->_do_query ( $sql, true );

		if ( $res == false ) return $f;

		if ( $this->rows == 0 )
		{
			$this->free ( $res );
			return $f;
		}

		return $res;
	}

	function & single_row ( $sql, $show_query = false )
	{
		$res = $this->query ( $sql, $show_query );

		if ( $res == false ) return $res;

		if ( is_array ( $res ) ) return ( $res [ 0 ] );

		$vals = mysql_fetch_array ( $res );
		if ( $this->reduce ) $vals = $this->_reduce ( & $vals );
		$this->free ( $res );

		return $vals;
	}

	function multi_exec ( $sql )
	{
		if ( $sql == false ) return;

		$f = explode ( ";", $sql );

		reset ( $f );

		foreach ( $f as $val ) $this->exec ( $val );
	}

	function exec_file ( $fname )
	{
		o_out (  "<h1><font color=\"blue\">$fname</font></h1>" );
		$str = util_read_file ( $fname );
		$this->multi_exec ( $str );
	}


	function exec ( $sql, $show_error = true, $show_query = false )
	{
		$this->rows = 0;

		if ( strlen ( trim ( $sql ) ) == 0 ) return ( true );

		if ( $show_query ) o_out ( "<h1>SQL: $sql</h1>" );

		$res = $this->_do_query ( $sql, $show_error, false );
		if ( $res )
		{
			$this->rows = mysql_affected_rows ();
			return ( true );
		}

		return ( false );
	}

	function create_table ( $name, $fields )
	{
		$this->exec ( "DROP TABLE IF EXISTS " . $this->prefix . "_$name" );
		return ( $this->exec ( "CREATE TABLE " . $this->prefix . "_$name ( $fields )" ) );
	}

	function insert ( $table_name, $fields, $values )
	{
		return ( $this->exec ( "INSERT INTO " . $this->prefix . "_$table_name ($fields) VALUES ( $values )" ) );
	}

	function get_id ()
	{
		return ( mysql_insert_id ( $this->dbh ) );
	}

	function lock ( $table_name )
	{
		$this->exec ( "LOCK TABLES " . $table_name . " WRITE");
	}

	function unlock ()
	{
		$this->exec ( "UNLOCK TABLES" );
	}

	function & get_table_fields ( $table_name )
	{
		$fields = @ mysql_list_fields ( DB_NAME, $table_name, $this->dbh );

		if ( $fields == false ) return ( false );

		$cols	= mysql_num_fields ( $fields );

		$res    = array ();

		for ( $t = 0; $t < $cols; $t ++ )
			$res [ $t ] = array ( strtolower ( mysql_field_name ( $fields, $t ) ), mysql_field_type ( $fields, $t ), mysql_field_len ( $fields, $t ), mysql_field_flags ( $fields, $t ) );

		mysql_free_result ( $fields );

		return ( $res );
	}

	function table_has_field ( $table_name, $field_name )
	{
		$f = & $this->get_table_fields ( $table_name );

		if ( $f == false ) return ( false );

		$l = sizeof ( $f );

		$field_name = strtolower ( $field_name );

		for ( $t = 0; $t < $l; $t ++ )
			if ( $f [ $t ] == $field_name ) return ( true );

		return ( false );
	}

	function & get_table_list  ()
	{
		$tables = mysql_list_tables ( WB_DB_NAME );

		$res = array ();

		$t = 0;
	
		while ( ( $vals = mysql_fetch_row ( $tables ) ) )
			$res [ $t ++ ] = $vals [ 0 ];

		return ( $res );
	}

	function & create_key_array ( $sql )
	{
		$res = & $this->query ( $sql );
		if ( $res == false ) return $res;

		$arr = array ();
		while ( ( $vals = $this->fetch ( $res ) ) )
		{
			$arr [ $vals [ 0 ] ] = array_slice ( $vals, 1 );
		}
		$this->free ( $res );

		return ( $arr );
	}

	function & fetch_all ( $sql )
	{
		$cur = $this->query ( $sql );
		if ( ! $cur ) return $cur;

		$res = Array ();
		while ( $vals = & $this->fetch ( $cur ) ) $res [] = & $vals;

		$this->free ( $cur );

		return $res;
	}

	function free ( & $res )
	{
		if ( $res == false ) return;

		if ( is_array ( $res ) )
			unset ( $res );
		else
			mysql_free_result ( $res );
	}

	function & fetch ( & $res )
	{
		$vals = false;

		if ( $res )
		{
			$vals = mysql_fetch_array ( $res );
			if ( $this->reduce ) $vals = $this->_reduce ( & $vals );
		} 

		return $vals;
	}

	function num_rows () { return $this->rows; }

	function count ( $table_name, $conds = null )
	{
		if ( $conds ) $conds = " WHERE $conds";

		$v = $this->single_row ( "SELECT COUNT(*) AS c FROM $table_name $conds" );
		return $v [ 'c' ];
	}

	function get_error () { return mysql_error (); }

	// -----------------------------------------------------------------------------------------------------
	// INTERNAL METHODS
	// Everything below this line is for internal use only and should not attract any developer
	// -----------------------------------------------------------------------------------------------------
	function & _reduce ( & $vals )
	{
		$len = count ( $vals )/2;

                for ( $t = 0; $t < $len; $t ++ ) unset ( $vals [ $t ] );

		return $vals;
	}

	// This method open a pconnection to the database
	function _open ()
	{
		// Get right values for connection from the config class
		
		$db_url = DB_LOCATION; 
		$port	= DB_PORT;    
		$sock 	= DB_SOCKET; 

		if ( $port == "" )
		{
			if ( $sock != "" )	$db_url .= ":$sock";
		} else 
			$db_url .= ":$port";

		// Try a permanent connection
		$this->dbh = mysql_pconnect ( $db_url, DB_USER, DB_PASSWD );

		if ( $this->dbh == false )
		{
			$err  = "<table border=\"0\">";
			$err .= "<tr><td align=\"right\"><b>MySQL Err</b>:</td><td>" . mysql_error () . "</td></tr>";
			$err .= "<tr><td align=\"right\"><b>Location:</b></td><td>" . DB_LOCATION . "</td></tr>";
			$err .= "<tr><td align=\"right\"><b>Port:</b></td><td>" . $port . "</td></tr>";
			$err .= "<tr><td align=\"right\"><b>Socket:</b></td><td>" . $sock . "</td></tr>";
			$err .= "<tr><td align=\"right\"><b>User:</b></td><td>" . DB_USER . "</td></tr>";
			$err .= "</table>";

			util_display_error ( "Cannot establish a connection with MySQL", $err );

			return ( false );
		}

		if ( mysql_select_db ( DB_NAME, $this->dbh ) == false )
		{
			util_display_error ( "Cannot select the database", mysql_error () );
			return ( false );
		}

		return ( true );
	}

	function & _do_query ( $sql, $display_error = true )
	{
		if ( $this->debug ) error_log ( "$sql" );
	
		$res = @ mysql_query ( $sql, $this->dbh );

		if ( $res === true ) return $res;

		if ( ( $res == false ) && ( $display_error == true ) ) 
		{
			util_display_error ( "Query Failed.<br>SQL: $sql", mysql_error () );
		} else {
			if ( $res === false ) return ( $res );

			$this->rows = mysql_num_rows ( $res );
			$this->cols = mysql_num_fields ( $res );
		}

		return $res;
	}
}
?>
